package com.example.fizzbuzz.entity;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * 井字棋
 * @author duzhou
 * @version 2021/1/25
 */
public class TicTacToe {

    // 棋盘坐标（记录棋子的位置）
    private Character[][] board = {
            {'N', 'N', 'N'},
            {'N', 'N', 'N'},
            {'N', 'N', 'N'}
    };

    // 前一次下棋的玩家
    private char lastPlayer = 'N';

    /**
     * 玩家下棋
     * @param x 轴
     * @param y 轴
     */
    public String play(int x, int y) {
        checkAxis(x);
        checkAxis(y);
        lastPlayer = nextPlayer();
        setBox(x, y);
        if (isWin()) return "玩家" + lastPlayer + "获胜";
        if (draw()) return "平局";
        return "没有人获胜";
    }

    /**
     * 判断棋子是否占满了棋局
     * @return
     */
    private boolean draw() {
        for (Character[] characters : board) {
            for (Character character : characters) {
                if(character == 'N') return false;
            }
        }
        return true;
    }

    /**
     * 检查棋子是否超出了轴的边界
     * @param axis
     */
    private void checkAxis(int axis) {
        if (axis < 1 || axis > 3) {
            throw new RuntimeException("棋子的位置不能超出边界");
        }
    }

    /**
     * 当前由哪个玩家落子
     * @return
     */
    public char nextPlayer() {
        if(lastPlayer == 'X') return 'O';
        return 'X';
    }

    /**
     * 玩家落子
     * @param x 棋子 X 轴位置
     * @param y 棋子 y 轴位置
     */
    private void setBox(int x, int y) {
        if (board[x - 1][y - 1] != 'N') {
            throw new RuntimeException("棋子不能放在已经有棋子的地方");
        } else {
            board[x - 1][y - 1] = lastPlayer;
        }
    }

    /**
     * 判断是否获胜
     *  1. 判断水平线是否都是当前玩家
     *  2. 判断垂直线是否都是当前玩家
     *  3. 判断对角线是否都是当前玩家
     * @return
     */
    private boolean isWin() {
        for (int i = 0; i < 3; i++) {
            // 遍历水平线1/2/3，判断 y 轴是否都是当前玩家
            if(board[0][i] == lastPlayer && board[1][i] == lastPlayer && board[2][i] == lastPlayer) return true;
            // 遍历垂直线1/2/3，判断 x 轴是否都是当前玩家
            if(board[i][0] == lastPlayer && board[i][1] == lastPlayer && board[i][2] == lastPlayer) return true;
        }
        // 如果当前玩家占据了左上角到右下角的对角线，则当前玩家获胜
        if(board[0][0] == lastPlayer && board[1][1] == lastPlayer && board[2][2] == lastPlayer) return true;
        // 如果当前玩家占据了右上角到左下角的对角线，则当前玩家获胜
        if(board[2][0] == lastPlayer && board[1][1] == lastPlayer && board[0][2] == lastPlayer) return true;
        return false;
    }

}
